/*
 * Copyright (c) 2021 Huawei Device Co.,  Ltd.
 * Licensed under the Apache License,  Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,  software
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,  either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "keyboard_srv_stub.h"
#include <string.h>
#include "message_option.h"
#include "message_parcel.h"
#include "hilog_wrapper.h"
#include "keyboard_common.h"
#include "keyboard_errors.h"
#include "cashdevice_stub.h"
#include "keyboard_observer_proxy.h"

namespace SwanLink {
namespace  Finance{
using namespace OHOS;
int KeyboardSrvStub::OnRemoteRequest(uint32_t code,  MessageParcel& data,  MessageParcel& reply,  MessageOption& option) {
    KEYBOARD_HILOGD(KEYBOARD_SRV, "cmd = %{public}d, flags = %{public}d",
                   code, option.GetFlags());
    std::u16string descriptor = KeyboardSrvStub::GetDescriptor();
    std::u16string remoteDescriptor = data.ReadInterfaceToken();
    if (descriptor != remoteDescriptor) {
        KEYBOARD_HILOGE(KEYBOARD_SRV,  "Descriptor is not matched");
        return ERR_NAME_NOT_FOUND;
    }

    return CheckRequestCode(code,  data,  reply,  option);
}

int32_t KeyboardSrvStub::CheckRequestCode(const uint32_t code,
            MessageParcel& data, MessageParcel& reply, MessageOption& option) {
    switch (code) {
        case static_cast<int>(IKeyboardSrv::KEYBOARD_ISSM4ENABLED): {
            return IsSM4EnabledStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_GETSN): {
            return GetSNStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_CALCULATEMAC): {
            return CalculateMACStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_ENCRYPTDATA): {
            return EncryptDataStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_SETPINLENGTH): {
            return SetPINLengthStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_SETTEXTMODE): {
            return SetTextModeStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_CLEARTEXTMODE): {
            return ClearTextModeStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_LOADMASTERKEY): {
            return LoadMasterKeyStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_LOADUSERKEY): {
            return LoadUserKeyStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_UPDATEMASTERKEY): {
            return UpdateMasterKeyStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_UPDATEUSERKEY): {
            return UpdateUserKeyStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_DELETEUSERKEY): {
            return DeleteUserKeyStub(data, reply, option);
        }
        case static_cast<int>(IKeyboardSrv::KEYBOARD_LISTENFORPIN): {
            return ListenForPinStub(data, reply, option);
        }
        default: {
            return CashDeviceSrvStub::OnRemoteRequest(code, data,
                                      reply, option);
        }
    }
    return IPCObjectStub::OnRemoteRequest(code,  data,  reply,  option);
}

int32_t KeyboardSrvStub::IsSM4EnabledStub(MessageParcel& data,
                        MessageParcel& reply, MessageOption& option) {
    int handle = -1;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    KEYBOARD_HILOGE(KEYBOARD_SRV, "handle: %{public}d", handle);
    bool result = IsSM4Enabled(handle);
    WRITE_PARCEL_WITH_RET(reply, Bool, result, E_WRITE_PARCEL_ERROR);
    KEYBOARD_HILOGE(KEYBOARD_SRV, "handle: %{public}d, Bool: %{public}d", handle, result);
    return ERR_OK;
}
int32_t KeyboardSrvStub::GetSNStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    char sn[1024];
    int len = -1;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);

    int result = GetSN(handle, sn, len);
    WRITE_PARCEL_WITH_RET(reply, Int32, len, E_WRITE_PARCEL_ERROR);
    WRITE_BUFFER_WITH_RET(reply, String, sn, 1024, E_WRITE_PARCEL_ERROR);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t KeyboardSrvStub::CalculateMACStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyInfo *key = NULL;
    const char* plain = nullptr;
    int len = 0;
    char enc_data[2048] = { 0 };
    int enc_len = 8;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_BUFFER_WITH_RET(data, KeyInfo, key,
                        sizeof(KeyInfo), E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, len, E_READ_PARCEL_ERROR);
    int result = -10140;
    if (len > 0) {
       READ_BUFFER_WITH_RET(data, char, plain, len, E_READ_PARCEL_ERROR);
       result = CalculateMAC(handle, *key, (char*)plain, len, enc_data, enc_len);
    }

    WRITE_PARCEL_WITH_RET(reply, Int32, enc_len, E_WRITE_PARCEL_ERROR);
    WRITE_BUFFER_WITH_RET(reply, String, enc_data,
                 sizeof(enc_data), E_WRITE_PARCEL_ERROR);
    KEYBOARD_HILOGE(KEYBOARD_SRV, "1enc_data: %{public}s, enc_len : %{public}d",
                    enc_data, enc_len);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t KeyboardSrvStub::EncryptDataStub(MessageParcel& data,
                        MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyInfo* key = nullptr;
    const char* plain = " ";
    int len = 0;
    char enc_data[520] = { 0 };
    int len_enc = 8;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_BUFFER_WITH_RET(data, KeyInfo, key,
                        sizeof(KeyInfo), E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, len, E_READ_PARCEL_ERROR);
    int result = -10141;
    if (len > 0) {
       READ_BUFFER_WITH_RET(data, char, plain, len, E_READ_PARCEL_ERROR);
       result = EncryptData(handle, *key, (char*)plain, len, enc_data, len_enc);
    }
    KEYBOARD_HILOGE(KEYBOARD_SRV, "enc_data: %{public}s, enc_len : %{public}d",
                    enc_data, len_enc);
    WRITE_PARCEL_WITH_RET(reply, Int32, len_enc, E_WRITE_PARCEL_ERROR);
    WRITE_BUFFER_WITH_RET(reply, String, enc_data,
                         sizeof(enc_data), E_WRITE_PARCEL_ERROR);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;


    //EncryptData(

}
int32_t KeyboardSrvStub::SetPINLengthStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    int minLen = -1;
    int maxLen = -1;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, minLen, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, maxLen, E_READ_PARCEL_ERROR);

    int ret = SetPINLength(handle, minLen, maxLen);
    WRITE_PARCEL_WITH_RET(reply, Int32, ret, E_WRITE_PARCEL_ERROR);
    return ERR_OK;
}
int32_t KeyboardSrvStub::SetTextModeStub(MessageParcel& data,
                        MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    TextMode *mode = nullptr;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_BUFFER_WITH_RET(data, TextMode, mode,
                        sizeof(TextMode), E_READ_PARCEL_ERROR);

    int ret = SetTextMode(handle, *mode);
    WRITE_PARCEL_WITH_RET(reply, Int32, ret, E_WRITE_PARCEL_ERROR);
    return ERR_OK;
}
int32_t KeyboardSrvStub::ClearTextModeStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);

    ClearTextMode(handle);
    return ERR_OK;
}
int32_t KeyboardSrvStub::LoadMasterKeyStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyID masterKeyID;
    unsigned char* KeyValue = nullptr;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, masterKeyID, E_READ_PARCEL_ERROR);
    std::string strKeyValue;
    READ_PARCEL_WITH_RET(data, String, strKeyValue, E_READ_PARCEL_ERROR);
    KeyValue = (unsigned char*)strKeyValue.c_str();
    int result = LoadMasterKey(handle, masterKeyID, KeyValue);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t KeyboardSrvStub::LoadUserKeyStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyID masterKeyID;
    int32_t user_Key_Type;
     unsigned char* KeyValue = NULL;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, masterKeyID, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, user_Key_Type, E_READ_PARCEL_ERROR);
    std::string strKeyValue;
    READ_PARCEL_WITH_RET(data, String, strKeyValue, E_READ_PARCEL_ERROR);
    KeyValue = (unsigned char*)strKeyValue.c_str();
    int result = LoadUserKey(handle, masterKeyID,
                 (userKeyType)user_Key_Type, KeyValue);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t KeyboardSrvStub::UpdateMasterKeyStub(MessageParcel& data,
                          MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyID masterKeyID;
     unsigned char* KeyValue = NULL;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, masterKeyID, E_READ_PARCEL_ERROR);
    std::string strKeyValue;
    READ_PARCEL_WITH_RET(data, String, strKeyValue, E_READ_PARCEL_ERROR);
    KeyValue = (unsigned char*)strKeyValue.c_str();

    int result = UpdateMasterKey(handle, masterKeyID, KeyValue);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t KeyboardSrvStub::UpdateUserKeyStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyID masterKeyID;
    int32_t user_Key_Type;
     unsigned char* KeyValue = NULL;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, masterKeyID, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, user_Key_Type, E_READ_PARCEL_ERROR);
    std::string strKeyValue;
    READ_PARCEL_WITH_RET(data, String, strKeyValue, E_READ_PARCEL_ERROR);
    KeyValue = (unsigned char*)strKeyValue.c_str();

    int result = UpdateUserKey(handle, masterKeyID,
                             (userKeyType)user_Key_Type, KeyValue);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t KeyboardSrvStub::DeleteUserKeyStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    KeyID masterKeyID;
    int32_t user_Key_Type;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, masterKeyID, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, user_Key_Type, E_READ_PARCEL_ERROR);

    int result = DeleteUserKey(handle, masterKeyID, (userKeyType)user_Key_Type);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}

int32_t KeyboardSrvStub::ListenForPinStub(MessageParcel& data,
                         MessageParcel& reply, MessageOption& option) {
    int handle = -1;
    int timeout = -1;

    READ_PARCEL_WITH_RET(data, Int32, handle, E_READ_PARCEL_ERROR);
    // READ_BUFFER_WITH_RET(data, PinListener, listener,
    // sizeof(listener), E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, timeout, E_READ_PARCEL_ERROR);
    sptr<OHOS::IRemoteObject> remote = data.ReadRemoteObject();
    // sptr<IKeyboardObserver> observer = iface_cast<IKeyboardObserver>(remote);
    if (remote != nullptr) {
        proxy_ = iface_cast<KeyboardObserverProxy>(remote);
    } else {
        proxy_ = nullptr;
    }
    
    KEYBOARD_HILOGD(KEYBOARD_SRV, "listener pointer is %{public}d", proxy_ != nullptr);
    ListenForPin(handle, proxy_, timeout);
    return ERR_OK;
}

} // namespace Finance
} // namespace SwanLink
